package messages;

import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import security.Hash;
import security.crypto.SimmEncryption;
import utils.Base64Processing;
import utils.XmlSerializationUtils;

public class UserPassPKExchangeMessage implements Convertible {

	private static final long serialVersionUID = 1L;
	
	private String _username;
	
	private String _cipheredPubKey;
	
	public UserPassPKExchangeMessage(){		
	}
	
	public UserPassPKExchangeMessage(String username, String password, PublicKey publicKey){
		_username = username;
		
		Key passwordKey = SimmEncryption.generateKeyFromPassHash(Hash.getStringHash(password));
		
		String publicKeyString = Base64Processing.encodeData(publicKey.getEncoded());
		_cipheredPubKey = SimmEncryption.cipherString(publicKeyString, passwordKey);
	}
	
	public String getUsername(){
		return _username;
	}
	
	public PublicKey getPublicKey(String passHash){
		Key passwordKey = SimmEncryption.generateKeyFromPassHash(passHash);
		
		String publicKeyString = SimmEncryption.decipherString(_cipheredPubKey, passwordKey);
		byte[] publicKeyBytes = Base64Processing.decodeData(publicKeyString);
		
		try {
			KeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
			KeyFactory factory = KeyFactory.getInstance("RSA");
			return factory.generatePublic(keySpec);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}	
		return null;	
	}

	@Override
	public Element convertToCanonic(Document doc) {
		Element el = doc.createElement("UserPassPKExchangeMessage");

		if (_username != null) {
			Element childEl = doc.createElement("Username");
			childEl.setTextContent(_username);
			el.appendChild(childEl);
		} 
		
		if (_cipheredPubKey != null) {
			Element childEl = doc.createElement("CipheredPubKey");
			childEl.setTextContent(_cipheredPubKey);
			el.appendChild(childEl);

		} 

		return el;
	}

	@Override
	public Object convertFromCanonic(Element el) {
		this._username = XmlSerializationUtils.getTextValue(el, "Username");
		this._cipheredPubKey = XmlSerializationUtils.getTextValue(el, "CipheredPubKey");
		return this;
	}
}
